/**
 * @file
 */

#ifdef __WIN32
	#include <Windows.h>
#else
	#include <dlfcn.h>
#endif

#include <iostream>
#include <string>
#include <boost/filesystem.hpp>
#include <boost/lexical_cast.hpp>
#include "mocha/pointers.hpp"
#include "mocha/shared_library.hpp"

namespace fs = boost::filesystem;

namespace mocha {
shared_library::shared_library(void* lib): lib_(lib) {
	if (!lib_) {
		/*...*/
	}
}
shared_library::~shared_library() {
	close();
}
boost::shared_ptr<shared_library> shared_library::open(const fs::path& file) {
	void* lib = NULL;
	#ifdef WIN32
		lib = LoadLibraryA(file.string().c_str());
	#else
		lib = dlopen(file.string().c_str(), RTLD_NOW | RTLD_LOCAL);
	#endif
	if (!lib) {
		std::string error;
		#ifdef WIN32
			error = "error code " + boost::lexical_cast<std::string>(GetLastError());
		#else
			error = dlerror();
		#endif
		return boost::shared_ptr<shared_library>();
	}
	return boost::shared_ptr<shared_library>(new shared_library(lib));
}
void* shared_library::symbol(const std::string& name) {
	#ifdef WIN32
		return GetProcAddress(static_cast<HMODULE>(lib_), name.c_str());
	#else
		return dlsym(lib_, name.c_str());
	#endif
}
void shared_library::close() {
	#ifdef WIN32
		FreeLibrary(static_cast<HMODULE>(lib_));
	#else
		dlclose(lib_);
	#endif
}
}

